package org.dromara.apartment.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.dromara.apartment.domain.*;
import org.dromara.apartment.domain.bo.GraphInfoBo;
import org.dromara.apartment.domain.enums.ItemType;
import org.dromara.apartment.domain.vo.*;
import org.dromara.apartment.mapper.*;
import org.dromara.apartment.service.IRoomInfoService;
import org.dromara.common.area.core.AreaHierarchy;
import org.dromara.common.area.core.utils.AreaUtils;
import org.dromara.common.core.domain.vo.CityVo;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.PinYinUtil;
import org.dromara.common.core.utils.PositionUtil;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.dromara.apartment.domain.bo.ApartmentInfoBo;
import org.dromara.apartment.service.IApartmentInfoService;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 公寓管理Service业务层处理
 *
 * @author ckj
 * @date 2025-06-11
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ApartmentInfoServiceImpl implements IApartmentInfoService {

    private final ApartmentInfoMapper baseMapper;
    private final GraphInfoMapper graphInfoMapper;
    private final ApartmentFacilityMapper apartmentFacilityMapper;
    private final ApartmentLabelMapper apartmentLabelMapper;
    private final ApartmentFeeValueMapper apartmentFeeValueMapper;
    private final LabelInfoMapper labelInfoMapper;
    private final FacilityInfoMapper facilityInfoMapper;
    private final FeeValueMapper feeValueMapper;
    private final IRoomInfoService roomInfoService;

    /**
     * 查询公寓管理
     *
     * @param id 主键
     * @return 公寓管理
     */
    @Override
    public ApartmentInfoVo queryById(Long id){
        //1.查询公寓信息
        ApartmentInfoVo apartmentInfoVo = baseMapper.selectVoById(id);
        //2.查询图片列表
        List<GraphInfoVo> graphVoList = graphInfoMapper.selectListByItemTypeAndId(ItemType.APARTMENT,id);
        //3.查询标签列表
        List<LabelInfoVo> labelInfoList = labelInfoMapper.selectListByApartmentId(id);
        //4.查询配套列表
        List<FacilityInfoVo> facilityInfoList = facilityInfoMapper.selectListByApartmentId(id);
        //5.查询杂费列表
        List<FeeValueVo> feeValueVoList = feeValueMapper.selectListByApartmentId(id);
        //6.组装结果
        if(CollUtil.isNotEmpty(graphVoList)){
            apartmentInfoVo.setGraphBoList(graphVoList.stream().map(GraphInfoVo::getName).collect(Collectors.joining()));
            apartmentInfoVo.setGraphVoList(graphVoList);
        }
        apartmentInfoVo.setLabelInfoList(labelInfoList);
        apartmentInfoVo.setFacilityInfoList(facilityInfoList);
        apartmentInfoVo.setFeeValueVoList(feeValueVoList);
        return apartmentInfoVo;
    }

    /**
     * APP查询公寓管理
     *
     * @param id 主键
     * @return 公寓管理
     */
    @Override
    public ApartmentInfoVo queryAppInfoById(Long id) {
        //1.查询公寓信息
        ApartmentInfoVo apartmentInfoVo = baseMapper.selectVoById(id);
        if(ObjectUtil.isEmpty(apartmentInfoVo)){
            throw new ServiceException("公寓不存在!");
        }
        //2.查询图片列表
        List<GraphInfoVo> graphVoList = graphInfoMapper.selectListByItemTypeAndId(ItemType.APARTMENT,id);
        //3.查询标签列表
        List<LabelInfoVo> labelInfoList = labelInfoMapper.selectListByApartmentId(id);
        //4.查询配套列表
        List<FacilityInfoVo> facilityInfoList = facilityInfoMapper.selectListByApartmentId(id);
        //5.查询杂费列表
        List<FeeValueVo> feeValueVoList = feeValueMapper.selectListByApartmentId(id);
        //6.组装结果
        apartmentInfoVo.setGraphVoList(graphVoList);
        apartmentInfoVo.setLabelInfoList(labelInfoList);
        apartmentInfoVo.setFacilityInfoList(facilityInfoList);
        apartmentInfoVo.setFeeValueVoList(feeValueVoList);
        apartmentInfoVo.setRoomInfoVoList(roomInfoService.getThreeCostEffectiveRooms(id));
        return apartmentInfoVo;
    }

    /**
     * 分页查询公寓管理列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 公寓管理分页列表
     */
    @Override
    public TableDataInfo<ApartmentInfoVo> queryPageList(ApartmentInfoBo bo, PageQuery pageQuery) {
        Page<ApartmentInfoVo> result = baseMapper.selectVoPageList(pageQuery.build(), bo);
        result.getRecords().stream().forEach(item->{
             if(ObjectUtil.isAllNotEmpty(bo.getLongitude(),bo.getLatitude(),item.getLongitude(),item.getLatitude())){
                 item.setDistance(PositionUtil.getDistance(bo.getLongitude(),bo.getLatitude(),item.getLongitude(),item.getLatitude()));
             }
        });
        if(ObjectUtil.isNotEmpty(bo.getDistanceFirst()) && bo.getDistanceFirst()){
            // 按距离升序排序，null 值放在最后
            result.getRecords().sort(Comparator.comparingDouble(
                (ApartmentInfoVo item) -> item.getDistance() != null ? item.getDistance() : Double.MAX_VALUE
            ));
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的公寓管理列表
     *
     * @param bo 查询条件
     * @return 公寓管理列表
     */
    @Override
    public List<ApartmentInfoVo> queryList(ApartmentInfoBo bo) {
        LambdaQueryWrapper<ApartmentInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ApartmentInfo> buildQueryWrapper(ApartmentInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ApartmentInfo> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(ApartmentInfo::getId);
        lqw.like(StringUtils.isNotBlank(bo.getName()), ApartmentInfo::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getIntroduction()), ApartmentInfo::getIntroduction, bo.getIntroduction());
        lqw.eq(bo.getDistrictId() != null, ApartmentInfo::getDistrictId, bo.getDistrictId());
        lqw.like(StringUtils.isNotBlank(bo.getDistrictName()), ApartmentInfo::getDistrictName, bo.getDistrictName());
        lqw.eq(bo.getCityId() != null, ApartmentInfo::getCityId, bo.getCityId());
        lqw.like(StringUtils.isNotBlank(bo.getCityName()), ApartmentInfo::getCityName, bo.getCityName());
        lqw.eq(bo.getProvinceId() != null, ApartmentInfo::getProvinceId, bo.getProvinceId());
        lqw.like(StringUtils.isNotBlank(bo.getProvinceName()), ApartmentInfo::getProvinceName, bo.getProvinceName());
        lqw.eq(StringUtils.isNotBlank(bo.getAddressDetail()), ApartmentInfo::getAddressDetail, bo.getAddressDetail());
        lqw.eq(StringUtils.isNotBlank(bo.getLatitude()), ApartmentInfo::getLatitude, bo.getLatitude());
        lqw.eq(StringUtils.isNotBlank(bo.getLongitude()), ApartmentInfo::getLongitude, bo.getLongitude());
        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), ApartmentInfo::getPhone, bo.getPhone());
        lqw.eq(bo.getIsRelease() != null, ApartmentInfo::getIsRelease, bo.getIsRelease());
        return lqw;
    }

    /**
     * 新增公寓管理
     *
     * @param bo 公寓管理
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(ApartmentInfoBo bo) {
        ApartmentInfo add = MapstructUtils.convert(bo, ApartmentInfo.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            setAreaInfo(add,bo.getArea());
            setGraphInfo(add,bo.getGraphBoList());
            setFacilityInfo(add,bo.getFacilityInfoIds());
            setLabelInfo(add,bo.getLabelIds());
            setFeeValue(add,bo.getFeeValueIds());
        }
        return flag;
    }

    /**
     * 修改公寓管理
     *
     * @param bo 公寓管理
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(ApartmentInfoBo bo) {
        ApartmentInfo update = MapstructUtils.convert(bo, ApartmentInfo.class);
        //删除操作
        //1.删除图片列表
        LambdaQueryWrapper<GraphInfo> graphInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemType, ItemType.APARTMENT.getType()).
            eq(GraphInfo::getItemId,update.getId());
        graphInfoMapper.delete(graphInfoLambdaQueryWrapper);

        //2.删除配套列表
        LambdaQueryWrapper<ApartmentFacility> apartmentFacilityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        apartmentFacilityLambdaQueryWrapper.eq(ApartmentFacility::getApartmentId,update.getId());
        apartmentFacilityMapper.delete(apartmentFacilityLambdaQueryWrapper);

        //3.删除标签列表
        LambdaQueryWrapper<ApartmentLabel> apartmentLabelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        apartmentLabelLambdaQueryWrapper.eq(ApartmentLabel::getApartmentId,update.getId());
        apartmentLabelMapper.delete(apartmentLabelLambdaQueryWrapper);

        //4.删除杂费列表
        LambdaQueryWrapper<ApartmentFeeValue> apartmentFeeValueLambdaQueryWrapper = new LambdaQueryWrapper<>();
        apartmentFeeValueLambdaQueryWrapper.eq(ApartmentFeeValue::getApartmentId,update.getId());
        apartmentFeeValueMapper.delete(apartmentFeeValueLambdaQueryWrapper);

        validEntityBeforeSave(update);
        setAreaInfo(update,bo.getArea());
        setGraphInfo(update,bo.getGraphBoList());
        setFacilityInfo(update,bo.getFacilityInfoIds());
        setLabelInfo(update,bo.getLabelIds());
        setFeeValue(update,bo.getFeeValueIds());
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ApartmentInfo entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除公寓管理信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            // 检查所有记录是否都处于已删除状态
            List<ApartmentInfoVo> records = baseMapper.selectVoList(new LambdaQueryWrapper<ApartmentInfo>()
                .select(ApartmentInfo::getId, ApartmentInfo::getDelFlag)
                .in(ApartmentInfo::getId, ids));
            if (records.size() != ids.size()) {
                throw new ServiceException("部分记录不存在或已被删除");
            }
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 校验并批量恢复公寓信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean recoverWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (ids == null || ids.isEmpty()) {
            throw new ServiceException("恢复ID不能为空");
        }
        // 有效性校验
        if (Boolean.TRUE.equals(isValid)) {
            List<ApartmentInfo> records = baseMapper.selectDelFlagsByIds(ids);
            // 检查记录数是否匹配
            if (records.size() != ids.size()) {
                throw new ServiceException("部分记录不存在或已被删除");
            }
            // 检查是否全部为已删除状态
            boolean hasNotDeleted = records.stream()
                .anyMatch(item -> !item.getDelFlag());
            if (hasNotDeleted) {
                throw new ServiceException("存在非删除状态记录，无法恢复");
            }
        }
        // 执行恢复操作
        int updateCount = baseMapper.recoverByIds(ids, LoginHelper.getUserId());
        if (updateCount == 0) {
            throw new ServiceException("恢复失败，请检查记录状态");
        }
        return updateCount>0;
    }

    /**
     * 校验并批量永久删除公寓信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean foreverDeleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (ids == null || ids.isEmpty()) {
            throw new ServiceException("恢复ID不能为空");
        }
        // 有效性校验
        if (Boolean.TRUE.equals(isValid)) {
            List<ApartmentInfo> records = baseMapper.selectDelFlagsByIds(ids);
            // 检查记录数是否匹配
            if (records.size() != ids.size()) {
                throw new ServiceException("部分记录不存在或已被删除");
            }
            // 检查是否全部为已删除状态
            boolean hasNotDeleted = records.stream()
                .anyMatch(item -> !item.getDelFlag());
            if (hasNotDeleted) {
                throw new ServiceException("存在非删除状态记录，无法永久删除");
            }
        }
        // 执行恢复操作
        int deleteCount = baseMapper.foreverDeleteByIds(ids);
        if (deleteCount == 0) {
            throw new ServiceException("永久删除失败，请检查记录状态");
        }
        return deleteCount>0;
    }

    /**
     * 修改状态
     *
     * @param bo 状态
     * @return 结果
     */
    @Override
    public int updateStatus(ApartmentInfoBo bo) {
        ApartmentInfoVo apartmentInfoVo=baseMapper.selectVoById(bo.getId());
        if(ObjectUtil.isEmpty(apartmentInfoVo)){
            throw new ServiceException("公寓不存在");
        }
        return baseMapper.update(null,
            new LambdaUpdateWrapper<ApartmentInfo>()
                .set(ApartmentInfo::getIsRelease, bo.getIsRelease())
                .eq(ApartmentInfo::getId, bo.getId()));
    }

    /**
     * 查询已开通城市
     *
     * @return
     */
    @Override
    public List<CityVo> getOpenCity() {
        List<CityVo> cityVoList=baseMapper.selectOpenedCities();
        if(CollUtil.isNotEmpty(cityVoList)){
            cityVoList.stream().forEach(item->{
                item.setPinyinInitials(PinYinUtil.getCityPinyinInitials(item.getName()));
            });
        }
        return cityVoList;
    }

    /**
     * 设置区域信息
     * @param entity 目标实体
     * @param areaIds 区域ID列表
     */
    private void setAreaInfo(ApartmentInfo entity, List<Integer> areaIds) {
        if (CollUtil.isNotEmpty(areaIds)) {
            AreaHierarchy areaHierarchy = AreaUtils.getAreaHierarchy(areaIds);
            if (ObjectUtil.isNotEmpty(areaHierarchy)) {
                // 设置区域层级信息
                entity.setDistrictId(areaHierarchy.getDistrictId());
                entity.setDistrictName(areaHierarchy.getDistrictName());
                entity.setCityId(areaHierarchy.getCityId());
                entity.setCityName(areaHierarchy.getCityName());
                entity.setProvinceId(areaHierarchy.getProvinceId());
                entity.setProvinceName(areaHierarchy.getProvinceName());
            }
        }
    }

    /**
     * 插入图片信息
     * @param entity
     * @param graphInfos
     */
    private void setGraphInfo(ApartmentInfo entity,String graphInfos) {
        if (StrUtil.isNotBlank(graphInfos)){
            List<String> graphInfoBoList=StrUtil.split(graphInfos, ",");
            ArrayList<GraphInfo> graphInfoList = new ArrayList<>();
            for (String graphInfoId : graphInfoBoList) {
                GraphInfo graphInfo = new GraphInfo();
                graphInfo.setName(graphInfoId);
                graphInfo.setItemType(ItemType.APARTMENT.getType());
                graphInfo.setItemId(entity.getId());
                graphInfoList.add(graphInfo);
            }
            graphInfoMapper.insertBatch(graphInfoList);
        }
    }

    /**
     * 插入配套信息
     * @param entity
     * @param facilityInfoIds
     */
    private void setFacilityInfo(ApartmentInfo entity,List<Long> facilityInfoIds) {
        if (CollUtil.isNotEmpty(facilityInfoIds)){
            ArrayList<ApartmentFacility> apartmentFacilityList = new ArrayList<>();
            for (Long facilityId : facilityInfoIds) {
                ApartmentFacility apartmentFacility = new ApartmentFacility();
                apartmentFacility.setApartmentId(entity.getId());
                apartmentFacility.setFacilityId(facilityId);
                apartmentFacilityList.add(apartmentFacility);
            }
            apartmentFacilityMapper.insertBatch(apartmentFacilityList);
        }
    }

    /**
     * 插入标签信息
     * @param entity
     * @param labelIds
     */
    private void setLabelInfo(ApartmentInfo entity,List<Long> labelIds) {
        if (CollUtil.isNotEmpty(labelIds)){
            ArrayList<ApartmentLabel> apartmentLabelList = new ArrayList<>();
            for (Long labelId : labelIds) {
                ApartmentLabel apartmentLabel = new ApartmentLabel();
                apartmentLabel.setApartmentId(entity.getId());
                apartmentLabel.setLabelId(labelId);
                apartmentLabelList.add(apartmentLabel);
            }
            apartmentLabelMapper.insertBatch(apartmentLabelList);
        }
    }

    /**
     * 插入杂费信息
     * @param entity
     * @param feeValueIds
     */
    private void setFeeValue(ApartmentInfo entity,List<Long> feeValueIds) {
        if (CollUtil.isNotEmpty(feeValueIds)){
            ArrayList<ApartmentFeeValue> apartmentFeeValueList = new ArrayList<>();
            for (Long feeValueId : feeValueIds) {
                ApartmentFeeValue apartmentFeeValue = new ApartmentFeeValue();
                apartmentFeeValue.setApartmentId(entity.getId());
                apartmentFeeValue.setFeeValueId(feeValueId);
                apartmentFeeValueList.add(apartmentFeeValue);
            }
            apartmentFeeValueMapper.insertBatch(apartmentFeeValueList);
        }
    }




}
